#include "APP_Device.h"


//初始化 网关设备信息结构体    linux万物皆是文件流的形式
Device* APP_Device_Init(char* file_name)
{
    //打开网关设备文件
    int fd = open(file_name,O_RDWR,0666);
    if(fd < 0)
    {
        perror("网关设备文件打开失败 ");
        return NULL;
    }

    //定义初始化 设备结构体 并为其分配空间
    Device* device = (Device*) malloc(sizeof(Device));
    if(device == NULL)
    {
        perror("设备结构体分配空间失败");
        return NULL;
    }

    device->Conn_type = conn_none;
    device->Dev_type = Device_None;
    device->fd = fd;
    device->file_name = file_name;
    device->post_read = NULL;
    device->pre_write = NULL;
    device->read_buff = APP_Buffer_Init(1024);
    device->write_buff = APP_Buffer_Init(1024);
    device->last_write_ts = 0;
    device->write_interval_ms = 100;
    device->running = 0;
    device->read_thread = 0;

    return device;
}

//启动网关设备 阻塞读取对端设备信息的线程任务
int APP_Device_Start(Device* device)
{
    log_info("APP_Device_Start");
    if(device == NULL)
    {
        return -1;
    }
    //创建一个线程
    int ret = pthread_create(&(device->read_thread),NULL,APP_Device_readfile,device);
    if(ret < 0)
    {
        perror("读取线程创建失败 ");
        return -1;
    }
    device->running = 1;
    // device->Conn_type = conn_bt;
    log_info("APP_Device_Start  over");
    return 0;
}

//从对端设备读取信息线程的执行函数 内容:1.将读取到的对端设备数据格式转化为 字节数组 2.并写入读取缓冲区 3.最后提交缓冲区数据发送mqtt的任务
// 读取数据->改格式为字节数组->写入读缓冲区->提交mqtt发送任务给线程池
void*APP_Device_readfile(void* arg)
{
    while(1)
    {
        Device* device = (Device*) arg;
        //当前设备是否运行
        if(device->running == 0)
        {
            perror("设备未启动");
            return NULL;
        }
        //定义一个临时缓冲区
        char temp_str[100] = {0};
        ssize_t read_len = read(device->fd,temp_str,100);
        //当读取到数据时
        if(read_len > 0)
        {
            log_info("APP_Device_readfile Start");
            //将对端设备格式数据 转 字节数组数据格式
            if(device->post_read)
            {
                read_len = device->post_read(device,temp_str,read_len);
            }
            if(read_len > 0)
            {
                //将字节格式数据 存入 读缓冲区
                log_info("从对端设备读取到的数据:");
                hexstr_print(temp_str,read_len);
                APP_Buffer_Write(device->read_buff,temp_str,read_len);
                //提交发送mqtt任务
                Task task = {.Task_fun = APP_Device_Mqtt_send,.arg = device};
                APP_Pool_Submit_Task(&task);     
            }
        }
    }
    return NULL;
}

//往线程池中提交发送mqtt的任务
void* APP_Device_Mqtt_send(void* arg)
{
    Device* device = (Device*)arg;
    //把数据从读取缓冲区中读出来
    char temp_str[100] = {0};
    int read_len = APP_Buffer_Read(device->read_buff,temp_str,100);

    //字节数组转为 msg格式->json格式
    Message* msg = APP_Bytes_To_Message(temp_str);
    char* json = APP_Message_To_Json(msg);
    log_info("发送到mqtt的json数据如下:");
    log_info("%s",json);
    //发送mqtt
    int ret = APP_MQTT_Send(json,strlen(json));
    if(ret == 0)
    {
        log_info("mqtt数据发送成功 ");
    }
    else{
        log_info("mqtt数据发送失败 ");
    }
}

//有路由器接收数据  接收上游数据处理数据格式 -> 存入写缓冲区 -> 提交写入对端设备的线程池任务
int APP_Device_recv_router(Device* device,char* data,int len)
{
    //字节数组存入写缓冲区
    APP_Buffer_Write(device->write_buff,data,len);
    if(device->write_buff->len < 0)
    {
        log_info("字节数组写入缓冲区失败");
    }
    
    log_info("write_buff:");
    hexstr_print(device->write_buff->ptr,device->write_buff->len);
    //提交线程池执行任务
    Task task = {.Task_fun = APP_Device_Writefile,.arg = device}; 
    int ret = APP_Pool_Submit_Task(&task);
    if(ret == 0)
    {
        log_info("路由模块提交线程池 成功");
    }
    else{
        log_info("路由模块提交线程池 失败");
    }
    return 0;
}

//将字节格式的数据 写入到对端设备中  处理数据格式->存入写缓冲区->提交线程池任务
void* APP_Device_Writefile(void* arg)
{
    log_info("开始往对端设备写入数据");
    //从写缓冲区中读取出数据
    Device* device = (Device*)arg;
    //把数据从读取缓冲区中读出来
    char temp_str[100] = {0};
    int read_len = APP_Buffer_Read(device->write_buff,temp_str,100);

    if(read_len > 0)
    {
        //将字节数组数据格式 -> 对端设备数据格式
        if(device->pre_write)
        {
            read_len = device->pre_write(device,temp_str,read_len);
        }
        if(read_len > 0)
        {
            log_info("往对端设备写入数据:");
            hexstr_print(temp_str,read_len);
            //判断当前最小时间间隔
            long long currt_time = APP_COM_Get_CurrtMs();
            long interval_ms = (currt_time - device->last_write_ts);
            log_info("当前时间戳currt_time_ms: %lld",currt_time);
            log_info("当前时间间隔interval_ms: %ld",interval_ms);
            //当前时间间隔 不满最小间隔 等待其满足最小间隔
            if(interval_ms < device->write_interval_ms)
            {
                usleep((device->write_interval_ms - interval_ms) * 1000);
            }
            write(device->fd,temp_str,read_len);
            //记录最后一次时间戳
            device->last_write_ts = APP_COM_Get_CurrtMs();
        }
    }
}

//释放设备资源
void APP_Device_free(Device *device)
{
    APP_Buffer_Free(device->read_buff);
    APP_Buffer_Free(device->write_buff);
    close(device->fd);
    free(device);
}

